import tkinter as tk
from tkinter import ttk, filedialog, scrolledtext
import base64
import os


class ImageToBase64Converter:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("图片转Base64编码工具")
        self.root.geometry("800x600")
        self.root.resizable(True, True)

        # 创建界面元素
        self.create_widgets()

        # 选择的文件路径
        self.selected_file_path = ""

    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 文件选择区域
        file_frame = ttk.LabelFrame(main_frame, text="选择图片文件", padding="10")
        file_frame.pack(fill=tk.X, pady=(0, 10))

        # 文件路径显示
        self.file_path_var = tk.StringVar(value="请选择图片文件...")
        path_frame = ttk.Frame(file_frame)
        path_frame.pack(fill=tk.X, pady=(0, 10))

        path_entry = ttk.Entry(path_frame, textvariable=self.file_path_var, state="readonly")
        path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))

        # 选择文件按钮
        browse_btn = ttk.Button(path_frame, text="浏览...", command=self.browse_file)
        browse_btn.pack(side=tk.RIGHT)

        # 文件信息显示
        info_frame = ttk.Frame(file_frame)
        info_frame.pack(fill=tk.X)

        self.file_info_var = tk.StringVar(value="文件信息: 无")
        info_label = ttk.Label(info_frame, textvariable=self.file_info_var)
        info_label.pack(anchor=tk.W)

        # 转换按钮
        convert_btn = ttk.Button(file_frame, text="转换为Base64", command=self.convert_to_base64)
        convert_btn.pack(pady=(10, 0))

        # 结果显示区域
        result_frame = ttk.LabelFrame(main_frame, text="Base64编码结果", padding="10")
        result_frame.pack(fill=tk.BOTH, expand=True)

        # Base64结果显示文本框
        self.result_text = scrolledtext.ScrolledText(result_frame, wrap=tk.WORD, height=20)
        self.result_text.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        # 操作按钮框架
        button_frame = ttk.Frame(result_frame)
        button_frame.pack(fill=tk.X)

        # 复制按钮
        copy_btn = ttk.Button(button_frame, text="复制到剪贴板", command=self.copy_to_clipboard)
        copy_btn.pack(side=tk.LEFT, padx=(0, 5))

        # 保存按钮
        save_btn = ttk.Button(button_frame, text="保存到文件", command=self.save_to_file)
        save_btn.pack(side=tk.LEFT, padx=(0, 5))

        # 清空按钮
        clear_btn = ttk.Button(button_frame, text="清空", command=self.clear_result)
        clear_btn.pack(side=tk.LEFT)

        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        status_bar = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(fill=tk.X, pady=(10, 0))

    def browse_file(self):
        """浏览并选择图片文件"""
        file_types = [
            ("图片文件", "*.png *.jpg *.jpeg *.gif *.bmp *.tiff"),
            ("PNG文件", "*.png"),
            ("JPEG文件", "*.jpg *.jpeg"),
            ("GIF文件", "*.gif"),
            ("BMP文件", "*.bmp"),
            ("TIFF文件", "*.tiff"),
            ("所有文件", "*.*")
        ]

        file_path = filedialog.askopenfilename(
            title="选择图片文件",
            filetypes=file_types
        )

        if file_path:
            self.selected_file_path = file_path
            self.file_path_var.set(file_path)

            # 显示文件信息
            try:
                file_size = os.path.getsize(file_path)
                file_name = os.path.basename(file_path)
                file_ext = os.path.splitext(file_path)[1].upper()
                self.file_info_var.set(
                    f"文件信息: {file_name} | 类型: {file_ext} | 大小: {self.format_file_size(file_size)}")
                self.status_var.set("文件已选择，点击'转换为Base64'按钮进行转换")
            except Exception as e:
                self.file_info_var.set(f"文件信息: 无法读取文件信息 - {str(e)}")

    def format_file_size(self, size_bytes):
        """格式化文件大小显示"""
        if size_bytes < 1024:
            return f"{size_bytes} B"
        elif size_bytes < 1024 * 1024:
            return f"{size_bytes / 1024:.2f} KB"
        elif size_bytes < 1024 * 1024 * 1024:
            return f"{size_bytes / (1024 * 1024):.2f} MB"
        else:
            return f"{size_bytes / (1024 * 1024 * 1024):.2f} GB"

    def convert_to_base64(self):
        """将选择的图片转换为Base64编码"""
        if not self.selected_file_path:
            self.status_var.set("错误: 请先选择图片文件")
            return

        try:
            self.status_var.set("正在转换...")
            self.root.update()

            # 读取图片文件并转换为Base64
            with open(self.selected_file_path, "rb") as image_file:
                encoded_string = base64.b64encode(image_file.read()).decode('utf-8')

            # 显示结果
            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(1.0, encoded_string)

            # 显示状态信息
            encoded_length = len(encoded_string)
            self.status_var.set(f"转换完成! Base64编码长度: {encoded_length} 字符")

        except Exception as e:
            self.status_var.set(f"转换失败: {str(e)}")
            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(1.0, f"转换失败: {str(e)}")

    def copy_to_clipboard(self):
        """复制Base64编码到剪贴板"""
        try:
            content = self.result_text.get(1.0, tk.END).strip()
            if content:
                self.root.clipboard_clear()
                self.root.clipboard_append(content)
                self.root.update()
                self.status_var.set("已复制到剪贴板")
            else:
                self.status_var.set("没有内容可复制")
        except Exception as e:
            self.status_var.set(f"复制失败: {str(e)}")

    def save_to_file(self):
        """保存Base64编码到文件"""
        try:
            content = self.result_text.get(1.0, tk.END).strip()
            if not content:
                self.status_var.set("没有内容可保存")
                return

            # 选择保存文件路径
            file_path = filedialog.asksaveasfilename(
                title="保存Base64编码",
                defaultextension=".txt",
                filetypes=[
                    ("文本文件", "*.txt"),
                    ("Base64文件", "*.b64"),
                    ("所有文件", "*.*")
                ]
            )

            if file_path:
                with open(file_path, "w", encoding="utf-8") as f:
                    f.write(content)
                self.status_var.set(f"已保存到: {file_path}")
        except Exception as e:
            self.status_var.set(f"保存失败: {str(e)}")

    def clear_result(self):
        """清空结果文本框"""
        self.result_text.delete(1.0, tk.END)
        self.status_var.set("结果已清空")

    def run(self):
        """运行程序"""
        self.root.mainloop()


if __name__ == "__main__":
    app = ImageToBase64Converter()
    app.run()
